package card

import (
	"fmt"
	"math/rand"
	"sort"
	"strconv"
	"time"
	"zinx_websokect_poker/zinx_app/poker_game/protocol"
)

func init(){
	//时间作为初始化种子
	rand.Seed(time.Now().UnixNano())
}

// Tcards 切片
type TCards []*TCard

func NewCards(nLen int) TCards {
	cards := make(TCards, nLen)
	//给牌堆里面的牌赋初始值
	for i := 0; i < nLen; i++ {
		pCard := NewCard(i+1) //牌值从1开始
		cards[i] = pCard
	}
	
	cards.randomize()
	
	return cards
}

func (self TCards) randomize(){
	for i := 0; i < len(self); i++ {
		nRand := rand.Intn(len(self) - 1) // 从 0 - 51 开始 ,52张牌
		// 两两指针进行交换
		self.Swap(i, nRand)
	}
}

func (self TCards) Len() int{
	return len(self)
}

func (self TCards) Less(i, j int) bool {
	//先比较点数
	if self[i].nPoint == self[j].nPoint {
		// 点数相同比较花色
		return self[i].nFlower > self[j].nFlower
	}
	return self[i].nPoint < self[j].nPoint
}

func (self TCards) Swap(i, j int) {
	// self[i].Swap(self[j])
	self[i], self[j] = self[j], self[i]
}

// 输出
func (self TCards) Tostr() string {
	// 顺带打印看结果
	strResult := ""
	for i := range self {
		strResult = strResult + self[i].tostr() + ","
	}
	return strResult
}

func (self TCards) getValue() string{
	// 顺带打印看结果
	strResult := ""
	for i := range self {
		strResult = strResult + strconv.Itoa(self[i].getValue()) + ","
	}
	return strResult
}

func (self TCards) GetValues() []int{
	var values []int
	for i := range self{
		values = append(values, self[i].nValue)
	}
	return values
}

func (self TCards) GetCombination() *protocol.Show{
	self.Sort()
	n := self.Len()
	nums := self.GetValues()
	point := toCardValues(nums)
	tmp := &protocol.Show{}
	if n == 2 {
		//第一回合，只要判断是否为对子
		tmp.Value = nums
		tmp.Point = point
		if point[0] == point[1]{
			tmp.Type = ONE_PAIR
			return tmp
		}
		tmp.Type = HIGH_CARD
		return tmp
	}
	m := 5
	//计算组合出来的牌
	indexs := zuheResult(n, m)
	result := findNumsByIndexs(nums, indexs)
	//循环获取形成的牌数组里的牌型
	//fmt.Println(result)
	for _, res := range result {
		//取出最大牌型返回
		s1 := GetType(res)

		if tmp.Type == 0 {
			tmp = s1
			continue
		}

		if !Showdown(tmp, s1){
			tmp = s1
		}
	}

	return tmp
}

func GetType(nums []int) *protocol.Show{
	var show protocol.Show
	var point []int
	var flower []int
	point = toCardValues(nums)
	flower = toFlowers(nums)
	show.Type = HIGH_CARD
	show.Value = nums
	show.Point = point
	//fmt.Println("点数：", point)
	//fmt.Println("花色：", flower)
	if res := RoyalFlush(point, flower); res > 0{
		show.Type=res
		goto ret
	}
	if res,s := StraightFlush(point, flower); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}
	if res,s := Four(point); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}
	if res,s := FullHouse(point); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}
	if res,s := Flush(flower, point); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}
	if res,s := Straight(point); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}
	if res,s := three(point); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}
	if res,s := TwoPair(point); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}
	if res,s := OnePair(point); res > 0{
		show.Type = res
		show.Struct = s
		goto ret
	}

	if show.Struct == nil {
		//高牌
		show.Struct = protocol.Flush{Cards: point}
	}
	ret:

	return &show
}

//比牌逻辑，返回show1
func Showdown(show1, show2 *protocol.Show) bool{
	// todo 比对两个show的type，如果相同，则根据牌型专属的struct再进行比对。

	//相同牌型，根据牌型专属的struct再进行比对。
	if show1.Type == show2.Type{
		var flag bool
		types := show1.Type
		switch types {
		case HIGH_CARD:
			str1 := show1.Struct.(protocol.Flush)
			str2 := show2.Struct.(protocol.Flush)
			flag = PkHighCard(str1, str2)
		case ONE_PAIR:
			str1 := show1.Struct.(protocol.OnePair)
			str2 := show2.Struct.(protocol.OnePair)
			flag = PkOnePair(str1, str2)
		case TWO_PAIR:
			str1 := show1.Struct.(protocol.TwoPair)
			str2 := show2.Struct.(protocol.TwoPair)
			flag = PkTwoPair(str1, str2)
		case THREE:
			str1 := show1.Struct.(protocol.Three)
			str2 := show2.Struct.(protocol.Three)
			flag  = PkThree(str1, str2)
		case FLUSH:
			str1 := show1.Struct.(protocol.Flush)
			str2 := show2.Struct.(protocol.Flush)
			flag = PkHighCard(str1, str2)
		case FULL_HOUSE:
			str1 := show1.Struct.(protocol.FullHouse)
			str2 := show2.Struct.(protocol.FullHouse)
			flag = PkFullHouse(str1, str2)
		case FOUR:
			str1 := show1.Struct.(protocol.Four)
			str2 := show2.Struct.(protocol.Four)
			flag = PkFour(str1, str2)
		case STRAIGHT:
			str1 := show1.Struct.(protocol.Straight)
			str2 := show2.Struct.(protocol.Straight)
			flag = PkStraight(str1, str2)
		}
		return flag
	}

	if show1.Type < show2.Type{
		return false
	}else {
		return true
	}

}

// 打印
func (self TCards) Print() {
	//log.Println(self.tostr())
	fmt.Println(self.Tostr())
	fmt.Println(self.getValue())
}

// 排序
func (self TCards) Sort() {
	sort.Sort(self)
}

